#pragma once

#include <memory>
#include <unordered_map>
#include "epoller.hpp"
#include "connection.hpp"
using namespace epollModule;

using connection_t = std::shared_ptr<connection>;
class reactor
{
    const static int event_num = 64;

private:
    bool isConnectionExist(int fd) { return _connections.count(fd); }

public:
    reactor() : _epoller(std::make_unique<epoller>()),
                    _isrunning(false)
    {
        init();
    }
    ~reactor()
    {
    }
    void init()
    {
        _epoller->init();
    }


    void insertConnection(connection_t conn)
    {
        if (!_connections.count(conn->sockfd()))
        {
            // zdl:: 把连接放到了 unordered_map中
            _connections[conn->sockfd()] = conn;
            // zdl::把新插入的连接。写透到内核的 epoll中
            _epoller->ctl(conn->sockfd(), conn->getEvents());
            // zdl:: 设置关联对象， 让connection回指当前对象
            conn->setOwner(this);
            LOG(LogLevel::DEBUG) << "add connection success: " << conn->sockfd();
        }
    }
// zdl:: 基于事件的事件派发器
    void dispatcher(int n)
    {
        for (int i = 0; i < n; i++)
        {
            // 开始进行派发, 拍发给指定的模块
            int sockfd = _revs[i].data.fd;
            uint32_t revents = _revs[i].events;
            if ((revents & EPOLLERR) || (revents & EPOLLHUP))
            {
                revents = (EPOLLIN | EPOLLOUT); // ! 异常事件，我们直接将这个转换为 IO事件，让异常在IO中被处理
            }
            if ((revents & EPOLLIN) && isConnectionExist(sockfd))
            {
                _connections[sockfd]->recever(); 
            }
            if ((revents & EPOLLOUT) && isConnectionExist(sockfd))
            {
                _connections[sockfd]->sender(); 
            }
        }
    }
    void loopOnce(int &timeout)
    {
        int n = _epoller->wait(_revs, event_num, timeout);
        dispatcher(n);
    }
    void debugPrint()
    {
        std::cout << "epoller 管理的 fd:";
        for (auto &iter : _connections)
        {
            std::cout << iter.first << " ";
        }
        std::cout << std::endl;
    }
    void loop()
    {
        _isrunning = true;
        int timeout = -1;
        while (_isrunning)
        {
            loopOnce(timeout);
            debugPrint();
            // 这里我们将其单独提出，就是为了做其他的工作
        }
        _isrunning = false;
    }
    void stop() { _isrunning = false; }

private:
    std::unique_ptr<epoller> _epoller;
    std::unordered_map<int, connection_t> _connections; // 服务器内部所有的连接
    int _isrunning;
    struct epoll_event _revs[event_num];
};